.model small
.stack 100h
.data
    Aprasas db "",10,13, "4. Zingsninio rezimo pertraukimo (int 1) apdorojimo procedura, atpazistanti", 10, 13, "komanda PUSH.",10,13
    Pagavau db "INT 1! "
    axx     dw ?          ;situose kur baigiasi x issisaugau reiksmes                    
    bxx     dw ?          ;pertraukimo pradzioje ir atstatau jas i
    cxx     dw ?          ;atitinkamus registrus kai pertraukimas baigiasi
    dxx     dw ?
    esx     dw ?
    bpx     dw ?
    Adresas db "0000"
    Pushas  db " Push "
    Zodis   db " Pirmas steko zodis="
    kodas   dw ?
    reg     dw ?
    enteris db 10,13
    reg2    dw ?
    posl    dw ?
    nerado  db "Kita komanda nera PUSH."
    six     dw ?
    
.code
Pradzia:
	MOV ax, @data
	MOV ds, ax
	
	MOV  cx, offset Pagavau
	MOV  dx, offset Aprasas
    CALL Spausdinti
    
    MOV	ax, 0				
	MOV	es, ax				
	MOV	bx, 4	
    
    PUSH es:[bx]
	PUSH es:[bx+2]
    
    MOV	dx, offset Apdoroti         ;standartinis INT 1 perrasymas nauja procedura
	MOV	es:[bx], dx			        
	MOV	es:[bx+2], cs			
	
    MOV ax, 1234h
    PUSH ax    
                        ;pasibandymai ar veikia
    INT 1
    PUSH [14:20]
       
    INT 1
    PUSH si[78]
    
    INT	1	
    PUSH bp

    INT 1
    PUSH cs 

    INT 1
    PUSH bx[si]

    INT 1	
    JMP Pabaiga
    
Spausdinti PROC                ;procedura, spausdinanti teksta i ekrana
    SUB cx, dx
    MOV ah, 40h
    MOV bx, 1
    INT 21h
    
    RET
Spausdinti ENDP

Apdoroti PROC                     ; :) pati INT apdorojimo procedura
    MOV [axx], ax                 ;issisaugau reiksmes
    MOV [bxx], bx
    MOV [cxx], cx
    MOV [dxx], dx
    MOV [esx], es
    MOV [bpx], bp
    MOV [six], si
    
    MOV  cx, offset axx              ;isvedu kad ivyko INT. Nereiketu to daryti taip anksti :D
	MOV  dx, offset Pagavau
    CALL Spausdinti
    
    MOV bp, sp                      
    MOV bx, [bp]                    ;i bx perkeliam kitos komandos cs reiksme
    MOV ax, [bp+2]                  ;i ax poslinki kode (ip)
    MOV es, ax
	MOV ax, es:[bx]                 ;o dabar jau taip gaunam sekancios komandos koda
	MOV [kodas], ax
	    
    MOV [posl], 0000h               ;apnulinu poslinki
    
    MOV bx, 0                        ;dabar atsirenkam kuri is 3 PUSH versiju cia yra
    AND al, 11100111b                
    CMP al, 00000110b
    JE JMP_PUSH_segreg 
    
    MOV ax, [kodas]
    AND al, 11111000b    
    CMP al, 01010000b
    JE JMP_PUSH_reg 
     
    MOV ax, [kodas]                   
    CMP al, 0FFh
    JNE Nera1
    
    AND ah, 00111000b
    CMP ah, 00110000b
    JNE Nera1 
;PUSH pats sunkiausias    
    MOV ax, [kodas]             ;kazkaip tas kodas apsivercia, jeigu buna 2 baitu, tai cia as ji atverciu   
    MOV bh, al
    MOV bl, ah
    MOV [kodas], bx
    
    MOV bx, 1                  ;sitas dalykas pades atsiminti procedurai Uzrasai1 kad kodas is 2 baitu, o ne vieno
    CALL Uzrasai1              ;uzraso keleta uzrasu :)
    
    MOV ax, [kodas]            ;dabar ziurim kokia mod reiksme kode
    AND al, 11000000b
    CMP al, 11000000b
    JE Mod11_2
    
    CMP al, 10000000b
    JE Mod10
        
    CMP al, 01000000b
    JNE Mod00 
    
Mod01:                         ;jeigu mod01, tai poslinkis 1 baitas
    MOV bp, sp
    MOV bx, [bp]
    MOV ax, [bp+2]
    MOV es, ax
	MOV ax, es:[bx+1]         ;gaunam sekanti baita, einanti po PUSH komandos
    
    MOV bl, ah               ;kadangi ax 2 baitai, o poslinkis 1 baito, tai 1 baita apnulinam  
    MOV bh, 0
    MOV [posl], bx           ;o likusi baita uzrasom i posl
    JMP Mod00                ; toliau viska vyksta alia su mod00

Mod10:
    MOV bp, sp               ;tada poslinkis 2 baitu, ir elgiames atitinkamai
    MOV bx, [bp]
    MOV ax, [bp+2]
    MOV es, ax
    MOV ax, es:[bx+2]
    MOV [posl], ax
	    
Mod00:
    MOV ax, [kodas]              ;dabar reikia atskirti, kokia lauko reg/m reiksme komandos kode
    AND al, 00000111b            ;jis parodys, kuri dalyka PUSHins
    
    CMP al, 0
    JE tai_bxsi
    
    CMP al, 1
    JE tai_bxdi
    
    CMP al, 2
    JE tai_bpsi_2
    
    CMP al, 3
    JE tai_bpdi_2
    JMP Toliau

Nera1:
    JMP Nera                 ;pora jumpu, kurie nepasieke tikslo

JMP_PUSH_segreg:
    JMP PUSH_segreg   
    
JMP_PUSH_reg:
    JMP PUSH_reg

Mod11_2:
    JMP Mod11

Toliau:  
    CMP al, 4
    JE tai_si_2    

    CMP al, 5    
    JE tai_di_2
    
    CMP al, 7
    JE tai_bx_2

    MOV cx, [posl]    
    CMP cx, 0
    JE tiesioginis
    
    MOV [reg], 'pb'         ;jeigu cia daejom, tai reiskia, kad pushins bp
    PUSH bp                 ;uzrasau i reg registro pavadinima ir issisaugau sena bp reiksme
    MOV bp, [bpx]           ;toliau randam ka des i steka komando po INT
    MOV si, [posl]
    MOV ax, bp[si]          ;ir pasidedam ta reiksme i ax
    POP bp
    
    JMP Uzrasai2            ;sokam kad uzrasytu galinius uzrasus
 
tiesioginis:                 ;tiesioginio adresavimo atvejis atrodo kiek kitaip
    MOV bp, sp
    MOV bx, [bp]
    MOV ax, [bp+2]
    MOV es, ax
    MOV cx, es:[bx+2]       ;adresas, i kuriame esanti daikta pushins, saugomas 2 baituose po PUSH komandos kodo
	
	MOV [posl], cx           ;issisaugosim adresa posl lauke.
	MOV bx, cx

    MOV ax, ds:[bx]
	PUSH ax
	
	JMP tiesioginis_print       

tai_bpsi_2:                  ;vel netilpo jump
    JMP tai_bpsi 
tai_bpdi_2:
    JMP tai_bpdi    

tai_bxsi:                     ;atitinkami atvejai kai PUSHina skirtingus dalykus
    MOV [reg],  'is'
    MOV [reg2], 'xb'
    
    MOV bx, [bxx]
    MOV si, [six]
    ADD si ,[posl]
    MOV ax, bx[si]    
    
    JMP Atspausdink2
    
tai_bxdi:
    MOV [reg],  'id'
    MOV [reg2], 'xb'
    
    MOV bx, [bxx]
    MOV si, di
    ADD si, [posl]
    MOV ax, bx[si]    
    
    JMP Atspausdink2

tai_si_2:
    JMP tai_si    
tai_di_2:
    JMP tai_di
tai_bx_2:
    JMP tai_bx    

tai_bpsi:
    MOV [reg],  'is'
    MOV [reg2], 'pb'
    
    PUSH bp
    MOV bp, [bpx]
    MOV si, [six]
    ADD si, [posl]
    MOV ax, bp[si]    
    POP bp
    
    JMP Atspausdink2

tai_bpdi:
    MOV [reg],  'id'
    MOV [reg2], 'pb'
    
    PUSH bp
    MOV bp, [bpx]
    MOV si, di
    ADD si, [posl]
    MOV ax, bp[si]    
    POP bp
    
    JMP Atspausdink2
   
Atspausdink2:                     ;sita dalis ivyksta tada, kai PUSHina koki tai 2 registru santyki pvz. bx[si]
    PUSH ax                       ;ax pasikeicia per sapusdinimo procedura, tai ji reik uzsaugot
    
    MOV dx, offset reg2
    MOV cx, offset posl
    CALL Spausdinti
    
    MOV ah,2
    MOV dl, ':'
    INT 21h
    
    POP ax
    JMP Uzrasai2
        
PUSH_reg:                       ;vienas is PUSH atveju. PUSHinamas registras be jokiu mod ir poslinkiu.
    CALL Uzrasai1
Mod11:                         ;atpazistama, kuri registra pushins
    MOV ax, [kodas]
    AND al, 00000111b
    
    CMP al, 0
    JE tai_ax
    
    CMP al, 1
    JE tai_cx
    
    CMP al, 2
    JE tai_dx
    
    CMP al, 3
    JE tai_bx
 
    CMP al, 4
    JE tai_sp
    
    CMP al, 5
    JE tai_bp
    
    CMP al, 6
    JE tai_si

Tai_di:    
    MOV reg, 'id'
    MOV si, [posl]              ;sitos kelios eilutes del poslinkio prirasytos tam,
    MOV bx, di                  ;kad ir atvejis su poslinkiu galetu cia nusokt.
    CMP si, 0
    JE  Be_posl
    JMP Su_posl
    
Tai_ax:                 ;cia negali nusokt atvejis su poslinkiu, taip kad maziau eiluciu :)
    MOV reg, 'xa'
    MOV ax, [axx]
    JMP Uzrasai2

Tai_cx:
    MOV reg, 'xc'
    MOV ax, [cxx]
    JMP Uzrasai2

Tai_dx:
    MOV reg, 'xd'
    MOV ax, [dxx]
    JMP Uzrasai2

Tai_bx:
    MOV reg, 'xb'
    MOV si, [posl]
    MOV bx, [bxx]
    CMP si, 0
    JE  Be_posl

Su_posl:                  ;pasirodo bx[0] visai nelygu bx, todel reikejo dvieju atveju
    MOV ax, bx[si]
    JMP Uzrasai2

Be_posl:
    MOV ax, bx
    JMP Uzrasai2

Tai_sp:
    MOV reg, 'ps'
    MOV ax, sp
    JMP Uzrasai2

Tai_bp:
    MOV reg, 'pb'
    MOV ax, [bpx]
    JMP Uzrasai2                    
    
Tai_si:
    MOV reg, 'is'
    MOV si, [posl]
    MOV bx, [six]
    CMP si, 0
    JE  Be_posl
    JMP Su_posl
        
PUSH_segreg:                  ;atvejis kai PUSHinamas segmento registras, Pats lengviausias atvejis.
    CALL Uzrasai1
    
    MOV ax, [kodas]           ;atpazistam kuri registra PUSHins
    AND al, 00011000b
    CMP al, 00000000b  ;ES=0, CS=1, DS=3, SS=2
    JE tai_es
    CMP al, 00001000b
    JE tai_cs
    CMP al, 00010000b
    JE tai_ss
    
    MOV reg, 'sd'
    MOV ax, ds
    JMP Uzrasai2

Tai_es:
    MOV reg, 'se'
    MOV ax, [esx]
    JMP Uzrasai2
     
Tai_cs:
    MOV reg, 'sc'
    MOV ax, [bp+2]
    JMP Uzrasai2
    
Tai_ss:
    MOV reg, 'ss'
    MOV ax, ss
    JMP Uzrasai2
    
Uzrasai2:                      ;stai cia parasoma antroji uzrasu dalis.
    PUSH ax                    ;jeigu jau cia atsidurem, reiskia ax saugoma reiksme, kuria des i steka
    
    MOV dx, offset reg         ;o reg uzrasyta su kuriuo registru dirbam
    MOV cx, offset enteris
    CALL Spausdinti
        
    MOV ax, [posl]             ;ar yra poslinkis?
    CMP ax, 0
    JE spausdink_lygu
    
    MOV ah,2                    ;jeigu yra, tai uzrasysim + poslinkis
    MOV dl, '+'
    INT 21h        
tiesioginis_print:              ;cia nusoka tiesioginio adresavimo atveju
    MOV ax,[posl]                ;atspausdinsim poslinki
    CALL Adresuoti
    
spausdink_lygu:    
    MOV ah,2
    MOV dl, '='
    INT 21h
        
    POP ax                      ;dabar issiimam is ax reiksme, kuria komanda po INT des i steka
    CALL Adresuoti              ;ir iskvieciam procedura, kuri atspausdins ta reiksme
    
    MOV dx, offset Zodis
    MOV cx, offset kodas
    CALL Spausdinti
            
    MOV ax, [bp+6]             ;cia pasiemam pirmaji dabartinio steko zodi
    CALL Adresuoti
        
    JMP INT_Pabaiga

Nera:                        ;sita spausdina kai po INT buna ne PUSHas... Nereiketu taip daryt.
    MOV dx, offset nerado
    MOV cx, offset six
    CALL Spausdinti    

INT_Pabaiga:                   ;pereina i kita eilute
    MOV dx, offset enteris
    MOV cx, offset reg2
    CALL Spausdinti
        
    MOV ax, [axx]             ;ir atstato buvusias reiksmes
    MOV bx, [bxx]
    MOV cx, [cxx]
    MOV dx, [dxx]
    MOV es, [esx]
    MOV bp, [bpx]
    MOV si, [six]
    IRET
Apdoroti ENDP

Adresuoti PROC                   ;pavercia 2 baitu registro reiksme i sesioliktainius skaicius ir atspausdina.
   LEA si, adresas               ;desim tai, ka spausdinsim i adresa
                                 ;tas, ka spausdinsim saugoma ax
Nulinam:                         ;apnulinam lauka "adresas"
    MOV dl, 30h
    MOV [si], dl
    INC si
    CMP si, offset Pushas
    JNE Nulinam
    
    LEA si, adresas              ;si rodo i lauko adresas pabaiga
    ADD si, 3
    MOV bx, 10h 

Dalyba:
                                
    MOV dx, 0
    DIV bx
    CMP dx, 0
    JNE Pridek
    CMP ax, 0
    JE Baigiam_adr
    
Pridek:    
    CMP dx, 9                    ;jeigu skaicius, tai reiks pridet 30h, kad pavirstu i ASCII skaiciu
    JBE pridek30
    
    ADD dx, 37h                 ;su raide reiks pridet 37h
    JMP tolyn 

Pridek30:
    ADD dx, 30h

Tolyn:                          ;taip po viena uzrasom skaiciuka
    MOV [si], dl
    DEC si
    JMP Dalyba      

Baigiam_adr:                    ;atspausdinam ka cia pagaminom
    MOV cx, offset Pushas
    MOV dx, offset Adresas
    CALL Spausdinti
    
    RET
Adresuoti ENDP

Uzrasai1 PROC             ;procedura uzraso pradine uzrasu dali
    PUSH bx               ;bx parodys, ar kodas vieno baito, ar dvieju
    MOV ax, [bp+2]        ;kitos po INT komandos cs reiksme
    CALL adresuoti
    
    MOV ah,2
    MOV dl, ':'
    INT 21h
    
    MOV ax, [bp]           ;ip reiksme
    CALL adresuoti
              
    MOV ah, 2
    MOV dl, ' '
    INT 21h

    MOV ax, [kodas]         
    POP bx
    CMP bx, 1
    JE palikti_ah
    
    MOV ah, 0             ;jeigu kodas 1 baito, tai reik apnulint ah
Palikti_ah:    
    CALL adresuoti          ;spausdins komandos koda
    
    MOV dx, offset Pushas   
    MOV cx, offset Zodis
    CALL Spausdinti
    RET    
Uzrasai1 ENDP

Pabaiga:	               ;main pabaiga
	POP	es:[bx+2]
	POP	es:[bx]
	
	MOV ah, 4Ch
	MOV al, 0
	INT 21h

END Pradzia    